var fs=require('fs'),path=require('path'),request = require('request'),_=require('underscore'),moment=require('moment'),MD5 = require('MD5');
var Afn={};
//获取网卡信息
Afn.getNetworkInfo=function(){
	var os=require('os');
	var nI=os.networkInterfaces();
	var ipLs=[],serverIps=[],ipList={};
	var realIp='';
	for(var i in nI){
		if(typeof(nI[i])!='object') continue;
		nI[i].forEach(function(v,k){
			if(Acan.regexp.ipv4.test(v.address)){
				if(Acan.inArr(v.address,['127.0.0.1','0.0.0.0'])) return;
				ipLs.push(v.address);
				ipList[v.address]=v.mac;
			}
			if(!v.internal) serverIps.push(v.address);
		});
	};
	serverIps.forEach(function(v){
		if(/^(10\.|192\.168\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[0-1]\.)/.test(v)){
			if(!realIp) realIp=v;
		}else if(/^[\d]{1,3}\.[\d]{1,3}\.[\d]{0,3}\.[\d]{1,3}$/.test(v)){
			if(!realIp || /(10\.|192\.168\.|172\.1[6-9]\.|172\.2[0-9]\.|172\.3[0-1]\.)/.test(realIp))
			realIp=v;
		}
	});
	return {serverIps:serverIps,ipMac:ipList,ips:ipLs,realIp:realIp};
}
//获取用户的头像路径
Afn.avatar_url=function(user,mode) {
	if (user && user.profile && user.profile.avatar) {
		return Afn.datatoUrl(user.profile.avatar, mode);
	}else if(user && user.avatar){
		return Afn.datatoUrl(user.avatar, mode);
	} else {
		return '/static/images/face/default.jpg';
	}
};
Afn.currencySymbol=function(c) {
	var currency={
		"CNY":"￥","CNH":"￥","EUR":"€","NZD":"$","PHP":"₱","USD":"$","AUD":"$"
	};
	return currency[c]?currency[c]:'';
};
/**
 * 邮件发送
 * @param mail
 * @param cb
 */
Afn.mail=function(mail,cb){
	var nodemailer = require('nodemailer');
	var transporter = nodemailer.createTransport({
		host: Aconf.mail.host,
		port: 25,
		auth: {
			user: Aconf.mail.user,
			pass: Aconf.mail.pass
		}
	});
	transporter.sendMail(mail,function(err,rs){
		// 邮件日志对象构建
		var log = {};
		log.from = mail.from;
		log.to = mail.to;
		log.note = mail.note ? mail.note : mail.html;
		log.subject = mail.subject;
		if (err) {
			log.status = -1;
			log.mark = JSON.stringify(err);
		} else {
			log.status = 3;
		}
		// 邮件日志记录
		Adb.email_log.add(log, function (err, rs) {
			Afn.logger.debug(err, rs);
		});
		if(cb) {
			cb(err, rs? rs: {});
		}
	});

		return;
	var mailer = require('mail').Mail({
		host: Aconf.mail.host,
		username: Aconf.mail.user,
		password: Aconf.mail.pass,
		port: Aconf.mail.port,
		domain: "[127.0.0.1]"
	});
	if (Acan.isStr(to)) {
		to = [to];
	}
	if (!Acan.isArr(to)) {
		if (cb) {
			cb('no mail');
		}
		return;
	}
	Afn.log(mailer, to);
	mailer.message({
		from: Aconf.mail.user, to: to, subject: title
	}).body(body).send(function (err, rs) {
		if (cb) {
			cb(err, rs);
		}
	});
};
/*
选择代理请求的服务器
用于代理需要指定服务器处理的请求
@ip 需要代理的ip （本身不使用代理，直接返回）
@domain 代理的域名
@cb 回调返回，是否使用了代理
*/
Afn.switchProxy=function(req,res,ip,domain,cb){
	if(Acan.objGet(Aconf,'ips.'+ip) && !Acan.isEmpty(Acan.intersection(Agl.serverIps,Aconf.ips[ip]))){
		//本身就是代理 直接返回
	}else if(Agl.serverIps.indexOf(ip)!==-1){
		//本身就是代理 直接返回
	}else{
		var request = require('request');
		var url="http://"+req.hostname.replace(req.getDomain(),domain)+req.url;
		request.get({url:url,json:true,pool: {maxSockets: Infinity}},function(err,rres,json){
			if(err){
				res.api_err(err);
				return;
			}
			res.api_rs(json);
		})
		return true;
	}
	return false;
}
//短信发送 自定义模板 模板貌似需要审核
Afn.smsSend=function(o,cb){
	if(Acan.regexp.mobile[86].test(o.mobile)){
		var url=Aconf.apiurl.bechsms+Acan.obj_form(Aconf.bechsms)+Acan.obj_form({'mobile':o.mobile,'content':o.note});
		request.get({url:url,json:true},function(err,res,json){
			if(Acan.isFun(cb)) cb(err,json);
		});
		return;
	}
}
/*
Mob短信发送
@o.mobile
@o.area_code
*/
Afn.mobSmsSend=function(o,cb){
	var data={appkey:Aconf.mobSms.appkey};
	data.phone=o.mobile;
	data.zone=o.area_code?o.area_code:'86';
	var url=Aconf.apiurl.mobSmsSend+'?'+Acan.obj_form(data);
	request.get({url:url,json:true,pool: {maxSockets: Infinity}},function(err,res,json){
		if(Acan.isFun(cb)) cb(err,json);
	});
}
/*
Mob短信验证
@o.mobile
@o.area_code
@o.captcha
*/
Afn.mobSmsCheck=function(o,cb){
	if(!Acan.isFun(cb)) return;
	var data={appkey:Aconf.mobSms.appkey};
	data.phone=o.mobile;
	data.zone=o.area_code?o.area_code:'86';
	data.code=o.captcha;
	var url=Aconf.apiurl.mobSmsCheck+'?'+Acan.obj_form(data);
	request.get({url:url,json:true,pool: {maxSockets: Infinity}},function(err,res,json){
		cb(err,json);
	});
}
/*
通用短信验证
@o.mobile
@o.area_code
@o.captcha
*/
Afn.smsCheck=function(o,cb){
	if(!Acan.isFun(cb)) return;
	var check=false;
	var error,rs;
	var ccb=Acan.ccb(2,function(){
		if(check){
			cb(null,1);
		}else{
			cb(error);
		}
	});
	//验证本地缓存
	Acache.get('captcha_'+o.mobile,function(err,rs){
		if(rs==o.captcha){
			check=true;
		}else{
			error="验证码错误";
		}
		Acache.del('captcha_'+o.mobile,function(err,num){});
		ccb.cb();
	});
	//验证mob短信
	Afn.mobSmsCheck(o,function(err,json){
		if(json && json.status==200){
			check=true;
		}else{
			error=err?err:'验证码错误';
		}
		ccb.cb();
	});
}
//weixin
Afn.passport_weixin=function(tp){
	//weixin平台
	var tpr=['mp','app','pc','mps'];
	if(tpr.indexOf(tp)===-1){
		tp='pc';
	}
	var weixinStrategy = require('passport-weixin');
	return new weixinStrategy({
		clientID: Aconf.connect.weixin[tp].key,
		clientSecret: Aconf.connect.weixin[tp].secret,
		callbackURL: "http://"+Aconf.api.host+"/connect/weixin/callback",
		requireState: false,
		scope: 'snsapi_login'
	}, Adb.member.connect_social_cb);
}
/**
 * DB初始化
 *
 * @param r //是否从缓存中重新加载
 */
Afn.dbinit=function(r,name) {    /* for emeditor*/
	Aconf.db_table_i = [];
	if(name){
		Adb[name] = Afn.require(Agl.root + 'model/' + name,r);
		if(name==='member') Afn.initPassport();
		return;
	}
	// DB模型加载到全局变量
	Aconf.db_table.forEach(function (val, i) {
		Adb[val.name] = {};
		val.tname = val.cname ? val.cname : val.name;
		Adb[val.name] = Afn.require(Agl.root + 'model/' + val.tname,r);
		if (val.id) {
			Aconf.db_table_i[val.id] = val.tname;
			Adb[val.name].id = val.id;
		}
	});
	Agl.db_status = true;
	Afn.cache_group(function () {
	});//加载用户组信息
	//--第三方认证
	Afn.initPassport();
};
//--单个模型 初始化
Afn.initModel=function(dbname,schema){
	var s_db;
	if(Mdb.models[dbname]){
		delete Mdb.models[dbname];
		s_db=Mdb.model(dbname, schema);
		//s_db=Mdb.models[dbname];
		//console.log(dbname,'has complite')
	}else{
		s_db=Mdb.model(dbname, schema);
		//console.log(s_db.compile,'new db')
	}
	return s_db
}
Afn.localDb=function(cb){
}
Afn.localDbInit=function(cb,f){
	if(typeof(LocalDb)!=='undefined' && !f){
		if(Acan.isFun(cb)) cb();
		return;
	}
	var MongoClient = require('mongodb').MongoClient;
	// Use connect method to connect to the Server
	MongoClient.connect('mongodb://nice9s.com:24001/local',Aconf.dbopts, function(err, db) {
		console.log("Connected correctly to server");
		global.LocalDb=db;
		if(Acan.isFun(cb)) cb();
		//db.close();
	});
}
//--第三方认证 初始化
Afn.initPassport=function() {    /* for emeditor*/
	var WeiboStrategy = require('passport-weibo-2').Strategy;
	Apassport.weibo = new WeiboStrategy({
		clientID: Aconf.connect.weibo.key,
		clientSecret: Aconf.connect.weibo.secret,
		callbackURL: "http://" + Aconf.api.host + "/connect/weibo/callback"
	}, Adb.member.connect_social_cb);
	//QQ网页平台
	var qqStrategy = require('passport-qq').Strategy;
	Apassport.qq = new qqStrategy({
		clientID: Aconf.connect.qq.key,
		clientSecret: Aconf.connect.qq.secret,
		callbackURL: "http://" + Aconf.api.host + "/connect/qq/callback"
	}, Adb.member.connect_social_cb);
	//QQ移动平台
	Apassport.qqm = new qqStrategy({
		clientID: Aconf.connect.qq_mobile.key,
		clientSecret: Aconf.connect.qq_mobile.secret,
		callbackURL: "http://" + Aconf.api.host + "/connect/qq/callback"
	}, Adb.member.connect_social_cb);
	//微信
	Apassport.weixin = Afn.passport_weixin('pc');//网站应用
	Apassport.weixinApp = Afn.passport_weixin('app');//移动应用
	Apassport.weixinMp = Afn.passport_weixin('mp');//订阅号
	Apassport.weixinMps = Afn.passport_weixin('mps');//服务号
	//facebook平台
	var facebookStrategy = require('passport-facebook').Strategy;
	Apassport.facebook = new facebookStrategy({
		clientID: Aconf.connect.facebook.key,
		clientSecret: Aconf.connect.facebook.secret,
		callbackURL: "http://" + Aconf.api.hkhost + "/connect/facebook/callback"
	}, Adb.member.connect_social_cb);
	//return;
	//twitter平台 TODO unreachable
	try {
		var twitterStrategy = require('passport-twitter').Strategy;
		Apassport.twitter = new twitterStrategy({
			consumerKey: Aconf.connect.twitter.key,
			consumerSecret: Aconf.connect.twitter.secret,
			callbackURL: "http://" + Aconf.api.hkhost + "/connect/twitter/callback"
		}, Adb.member.connect_social_cb);
	} catch (e) {
		Afn.log('stack', e.stack);
	}
}
/**
 * 语言绑定
 *
 * @param cb
 */
Afn.buildlang=function(cb) {
	var lpath = Agl.root + 'www/locales/';
	var start = 'var Alang=';
	var end = ";\ntry{module.exports=Alang;}catch(e){}";
	var ccb = Acan.ccb(Aconf.apps.length, function () {
		Afn.logger.debug('build lang OK');
		if (cb) {
			cb();
		}
	});
	Aconf.apps.forEach(function (app, k) {
		Adb.lang.find({"app": {$in: [app]}}).sort({code:1}).read('n').exec(function (err, docs) {
			if (err || !docs) {
				return;
			}
			var obj = {zh: {}, en: {}};
			docs.forEach(function (doc, k) {
				if (!doc.code) {
					return;
				}
				obj.zh[doc.code] = doc.zh;
				obj.en[doc.code] = doc.en;
			});
			Acan.mkdirs(lpath + app + '/');
			Acache.hset(Aconf.cache.lang, app, obj);
			_.each(obj, function (v, k) {
				var str = start + JSON.stringify(v).replace(/","/g,'",\n"') + end;
				fs.writeFileSync(lpath + app + '/' + k + '.js', str);
				//Afn.log(lpath+app+'/'+k+'.js',str);
			});
			ccb.cb();
		});
	});
};

//加载语言
Afn.loadlang = function (cb, f) {
	Acache.hgetall(Aconf.cache.lang, function (err, rs) {
		if (err) {
			Afn.logger.error('err', 'load lang err', err);
			//return false;
		}
		if (!rs) {
			if (!f && Adb.lang) {
				Afn.buildlang(function () {
					Afn.loadlang(cb, 1);
				});
			}
			Afn.logger.debug('load lang false');
			return false;
		}
		Glang = rs;
		Afn.logger.debug('load lang OK');
		if (cb) {
			cb();
		}
	});
};
Afn.loadplugin=function(cb,f){
	var call=function(err,rs){
		if(rs && rs[Appname]){
			Aplugin=rs[Appname];
		}
		if (cb) {
			cb();
		}
	}
	var dbGet=function(){
		var pbj={};
		Adb.plugin.find().read('n').exec(function(err,docs){
			if(docs){
				docs.forEach(function(v){
					if(!pbj[v.app]) pbj[v.app]={};
					if(!pbj[v.app][v.mod+'/'+v.act]) pbj[v.app][v.mod+'/'+v.act]={};
					pbj[v.app][v.mod+'/'+v.act][v.hk]={code:v.code,sort:v.sort};
				});
				/*
				for(var hk in pbj[v.app][v.mod+'/'+v.act]){
					pbj[v.app][v.mod+'/'+v.act][hk]=_.sortBy(pbj[v.app][v.mod+'/'+v.act][hk],'sort');
				};*/
				Acache.set(Aconf.cache.plugin,pbj);
			}
			call(err,pbj);
		});
	}
	if(f){
		dbGet();
	}else{
		Acache.get(Aconf.cache.plugin, function (err, rs) {
			if (err || !rs) {
				if (!f && Adb.plugin) {
					//缓存中没有从数据库获取
					dbGet();
				}else{
					call(err,rs);
				}
			}else{
				call(err,rs);
			}
		});
	}
}
//加载全局配置选项
Afn.loadopts=function(cb,f){
	var call=function(err,rs){
		if(err || !rs){
			Afn.log('load opts false', Appname);
		}else{
			for(var i in rs){
				if(Acan.isJSON(rs[i])){
					try{
						rs[i]=JSON.parse(rs[i]);
					}catch(e){}
				}
			};
			Aopts=rs;
			Afn.logger.debug('load opts OK', Appname);
		}
		if (cb) {
			cb();
		}
	}
	var dbGet=function(){
		Adb.conf.find({tp:'system'}).read('n').exec(function (err,docs) {
			if(docs){
				var obj={};
				docs.forEach(function(v){
					obj[v.key]=v.val;
				});
				Acache.set(Aconf.cache.opts,obj);
			}
			call(err,obj);
		});
	}
	if(f){
		dbGet();
	}else{
		Acache.get(Aconf.cache.opts, function (err, rs) {
			if (err || !rs) {
				if (!f && Adb.conf) {
					//缓存中没有从数据库获取
					dbGet();
				}else{
					call(err,rs);
				}
			}else{
				call(err,rs);
			}
		});
	}
}
//获取微信access_token
Afn.weixinAccessToken=function(cb){
	var key='weixinAccessToken';
	var getNewToken=function(){
		var appid=Aconf.connect.weixin.mps.key;
		var secret=Aconf.connect.weixin.mps.secret;
		var url='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='+appid+'&secret='+secret;
		request.get({url: url, json: true,pool: {maxSockets: Infinity}}, function (err, r, json) {
			if (err) {
				cb(err)
				return;
			}
			var access_token=Acan.objGet(json,'access_token');
			if(!access_token){
				cb('get access_token faild')
				return;
			}
			cb(null,access_token);
			json.time=Acan.time();
			var jsonstr=JSON.stringify(json);
			Acache.hset(Aconf.cache.opt_one,key,jsonstr);
			Adb.conf.findOne({key:key}).exec(function (err,doc) {
				if(err){
					return;
				}
				if(!doc){
					doc=new Adb.conf();
					doc.set('key',key);
				}
				doc.set('val',jsonstr);
				doc.save(function(err){});
			});
			return;
		});
	}
	Afn.optGet(key,function(err,rs){
		if(rs && rs.access_token && (rs.time+7200) > Acan.time()){
			cb(err,rs.access_token);
			return;
		}
		getNewToken();
	})
}
Afn.weixinJsapiTicket=function(cb){
	var key='weixinJsapiTicket';
	var getNewToken=function(){
		var appid=Aconf.connect.weixin.mps.key;
		var secret=Aconf.connect.weixin.mps.secret;
		Afn.weixinAccessToken(function(err,access_token){
			if(err){
				cb(err);
				return;
			}
			var url='https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token='+access_token;
			request.get({url: url, json: true,pool: {maxSockets: Infinity}}, function (err, r, json) {
				if (err) {
					cb(err)
					return;
				}
				var ticket=Acan.objGet(json,'ticket');
				if(!ticket){
					cb('get JsapiTicket faild')
					return;
				}
				cb(null,ticket);
				json.time=Acan.time();
				var jsonstr=JSON.stringify(json);
				Acache.hset(Aconf.cache.opt_one,key,jsonstr);
				Adb.conf.findOne({key:key}).exec(function (err,doc) {
					if(err){
						return;
					}
					if(!doc){
						doc=new Adb.conf();
						doc.set('key',key);
					}
					doc.set('val',jsonstr);
					doc.save(function(err){});
				});
				return;
			});

		})
	}
	Afn.optGet(key,function(err,rs){
		if(rs && rs.ticket && (rs.time+7200) > Acan.time()){
			cb(err,rs.ticket);
			return;
		}
		getNewToken();
	})
}
//微信模版消息发送
Afn.weixinTemplateSend = function (openid,obj,cb) {
	if(!openid){
		cb('no openid');
		return;
	}
	Afn.weixinAccessToken(function(err,access_token){
		if(err){
			cb('no access_token');
			return;
		}
		var url='https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' + access_token;
		obj.touser=openid;
		request.post(url, {
			form: JSON.stringify(obj)
		}, function (err, res, json) {
			cb(err,json);
		});
	});
}
//获取配置选项
Afn.optGet=function(key,cb,f){
	var call=function(err,rs){
		if(Acan.isJSON(rs)){
			try{
				rs=JSON.parse(rs);
			}catch(e){}
		}
		cb(err,rs);
	}
	var dbGet=function(){
		Adb.conf.findOne({key:key}).read('n').exec(function (err,doc) {
			if(err || !doc){
				return call('no conf');
			}
			if(doc){
				doc.val;
				Acache.hset(Aconf.cache.opt_one,key,doc.val);
			}
			call(err,doc.val);
		});
	}
	if(f) dbGet();
	else
		Acache.hget(Aconf.cache.opt_one,key, function (err, rs) {
			if (err || !rs) {
				if (!f && Adb.conf) {
					//缓存中没有从数据库获取
					dbGet();
				}else{
					call(err,rs);
				}
			}else{
				call(err,rs);
			}
		});
}
//mongodb->redis 加速读取 一些配置可以缓存到内存中
/*
 TODO:
*/
Afn.cache=function(pre,key,cb){
	if(arguments.length==2){
		if(Acan.isFun(key)) cb=key;
		key=pre;
	}
}
//mongodb->redis 哈希加速读取 一些配置可以缓存到内存中
Afn.cacheh=function(){
	
}
//加载
Afn.require=function(rpath,r) {
	if(r) delete require.cache[require.resolve(rpath)];//重载前删除缓存
	return require(rpath);
}
//加载控制器
Afn.loadcontrol=function(Appname,ver) {
	var mods={};
	var pubPath = Agl.root + 'mod/pub';//公共模块
	var mpath = Agl.root + 'mod/' + Appname;
	if(Appname==='api'){
		if(ver){
			mpath+='/'+ver;
		}else{
			var apiDir = fs.readdirSync(mpath);
			apiDir.forEach(function (val, i) {
				var npath = mpath + '/' + val;
				if (fs.lstatSync(npath).isDirectory()) {
					Afn.loadcontrol(Appname,val);
				}
			});
			return;
		}
	}
	//读取APP私有模块
	if (fs.existsSync(mpath)) {
		var aDir = fs.readdirSync(mpath);
		aDir.forEach(function (val, i) {
			if(val.substr(-3)!=='.js') return;
			var npath = mpath + '/' + val;
			var mod = val.replace('.js', '');
			if (fs.lstatSync(npath).isFile()) {
				mods[mod] = Afn.require(npath,1);
			}
		});
	}
	//读取公共模块
	if (fs.existsSync(pubPath) && Appname!=='api') {
		var mdir = fs.readdirSync(pubPath);
		mdir.forEach(function (val, i) {
			if(val.substr(-3)!=='.js') return;
			var npath = pubPath + '/' + val;
			var mod = val.replace('.js', '');
			if (!mods[mod] && fs.lstatSync(npath).isFile()) {
				mods[mod] = Afn.require(npath,1);
			}
		});
	}
	if(Appname==='api'){
		if(!Acontrol[Appname]) global.Acontrol[Appname]={};
		global.Acontrol[Appname][ver]=mods;
	}else{
		global.Acontrol[Appname]=mods;
	}
};
//加载枚举
Afn.loadenum = function () {
	var lpath = Agl.enumpath;
	if (!fs.existsSync(lpath)) {
		return;
	}
	var ldir = fs.readdirSync(lpath);
	ldir.forEach(function (val, i) {
		var npath = lpath + '/' + val;
		if (fs.lstatSync(npath).isDirectory()) {
			Afn.loadenum_c(val, npath);
		}
	});
};

Afn.loadenum_c = function (lang, lpath) {
	if (!Aenum[lang]) {
		Aenum[lang] = {};
	}
	var ldir = fs.readdirSync(lpath);
	ldir.forEach(function (val, i) {
		var npath = lpath + '/' + val;
		if (fs.lstatSync(npath).isFile()) {
			try {
				Aenum[lang][val.replace('.js', '')] = require(npath);
			} catch (e) {
				Afn.log('stack', 'enum load err:', npath, e.stack);
			}
		}
	});
};

//enum对象转key数组
Afn.enum2key=function(emrr){
	var arr=[];
	emrr.forEach(function(v,k){
		arr.push(v.code);
	});
	return arr;
}


//model id to model name;
Afn.id_tbname=function(tp){
	if(Acan.isInts(tp)){
		if(Aconf.db_table_i[tp]) {
			tp = Aconf.db_table_i[tp];
		}
	}
	return tp;
};
Afn.push_device=function(obj,cb){
	var drr=['phone','android'];
	var error=null,rs=[];
	Acache.hget(Aconf.cache.device, obj.to, function (err, dev) {
		if (!dev || (!dev.phone && !dev.android)) {
			return cb('no device');
		}
		var device;
		if(dev.phone){
			device=dev.phone;
		}else if(dev.android){
			device
		}
		var ccb=Acan.ccb(drr.length,function(err,data){
			if(!error && err){
				error=err;
				Afn.log(err);
			}
			if(!err) rs.push(data);
		},function(){
			if(rs.length>0){
				error=null;
			}
			if(Acan.isFun(cb)) cb(error,rs);
		});
		['phone','android'].forEach(function(d){
			if(!dev[d]){
				ccb.cb('no '+d);
				return;
			}
			if(dev[d].xg){
				Afn.push_XG(obj,dev[d],function(e,d){ccb.cb(e,d);});
			}else if(dev[d].token){
				Afn.push_umeng(obj,dev[d],function(e,d){ccb.cb(e,d);});
			}
		});
	});
}
//从cache推送消息至信鸽 XG
Afn.push_XG = function (obj,dev,cb) {
	var Xinge = require(Agl.root+'lib/push/Xinge');
	var accessId,secretKey,args=[];
	args.push(obj.to);
	if (dev.model.indexOf('iPhone') !== -1 || dev.model.indexOf('iPad') !== -1) {
		accessId  = 2200113301;
		secretKey = '22f7548f479e2c6f346201439308f9c4';
		//IOS message start.
		var iOSMessage = new Xinge.IOSMessage();
		iOSMessage.alert = obj.alert;
		iOSMessage.badge = 1;
		iOSMessage.sound = 'df';
		iOSMessage.acceptTime.push(new Xinge.TimeInterval(0, 0, 23, 0));
		/*iOSMessage.customContent = {
			key1: 'value1',
			key2: 'value2'
		};*/
		//iOSMessage.loopTimes = 3;
		//iOSMessage.loopInterval = 2;
		//IOS message end.
		args.push(iOSMessage);
		args.push(1);
	} else {
		accessId  = 2100113300;
		secretKey = 'c51317e830ae328a05752704265a53fa';
		//Android message start.
		var style = new Xinge.Style();
		style.ring = 1;
		style.vibrate = 0;
		style.ringRaw = 'a';
		style.smallIcon = 'b';
		style.builderId = 77;
		var action = new Xinge.ClickAction();
		action.actionType = Xinge.ACTION_TYPE_ACTIVITY;
		//action.packageName.packageName = 'com.demo.xg';
		//action.packageName.packageDownloadUrl = 'http://a.com';
		//action.packageName.confirm = 1;
		var androidMessage = new Xinge.AndroidMessage();
		androidMessage.type = Xinge.MESSAGE_TYPE_NOTIFICATION;
		androidMessage.title = 'a';
		androidMessage.content = obj.alert;
		androidMessage.style = style;
		androidMessage.action = action;
		androidMessage.sendTime = Acan.time();
		androidMessage.expireTime = 0;
		//androidMessage.acceptTime.push(new Xinge.TimeInterval(0, 0, 23, 59));
		//androidMessage.customContent = {
		//	'name': 'huangnaiang'
		//};
		androidMessage.multiPkg = 0;
		//androidMessage.loopTimes = 3;
		//androidMessage.loopInterval = 2;
		//And message end.
		args.push(androidMessage);
	}
	args.push(function(err,rs){
		Afn.log('xg push ',err,rs)
		cb(err,rs);
	});
	//推送消息给指定设备
	var XingeApp = new Xinge.XingeApp(accessId, secretKey);
	XingeApp.pushToSingleAccount.apply(XingeApp,args);
}
//从cache推送消息至umeng
Afn.push_umeng = function (obj,dev,cb) {
	var post = {};
	var allow = {type: ['unicast', 'broadcast', 'groupcast', 'customizedcast', 'filecast']};
	var umeng = Aconf.openapi.umeng;
	var timestamp = Acan.time();
	var validation_token = MD5(umeng.key + umeng.secret + timestamp);
	post = {appkey: umeng.key, timestamp: timestamp, validation_token: validation_token};
	post.device_tokens = dev.token;
	//post.device_tokens='5d93112e281b396017bc767d1940d14f6113ccb911b92ee8c61e52d7cbace739';
	post.type = 'unicast';
	//单播消息无token退出
	if (post.type === 'unicast' && post.device_tokens && post.device_tokens.length < 1) return cb('no device_tokens');
	post.payload = {};
	var pbj = {};
	//IOS
	if (dev.model.indexOf('iPhone') !== -1 || dev.model.indexOf('iPad') !== -1) {
		pbj.aps = {alert: obj.alert};
		pbj.note = obj.note;
		pbj.tp = obj.tp;
		pbj.to = obj.to;
		pbj.date = obj.date;
		pbj.ev = obj.ev;
	} else {
		pbj.display_type = 'notification';//notification或者message
		pbj.body = {
			"ticker": "xx",		// 必填 通知栏提示文字
			"title": "xx",		// 必填 通知标题
			"text": "xx",		// 必填 通知文字描述
			//"builder_id": xx	// 可选 默认为0
			"icon": "xx",		// 可选 状态栏图标ID, R.drawable.[smallIcon],如果没有, 默认使用应用图标。 图片要求为24*24dp的图标,或24*24px放在drawable-mdpi下。
			"largeIcon": "xx",	// 可选 通知栏拉开后左侧图标ID, R.drawable.[largeIcon]. 图片要求为64*64dp的图标,可设计一张64*64px放在drawable-mdpi下, 注意图片四周留空，不至于显示太拥挤
			"img": "xx",		// 可选 通知栏大图标的URL链接。该字段的优先级大于largeIcon。该字段要求以http或者https开头。
			"play_vibrate": "true/false",	// 可选 收到通知是否震动,默认为"true".注意，"true/false"为字符串
			"play_lights": "true/false",		// 可选 收到通知是否闪灯,默认为"true"
			"play_sound": "true/false",		// 可选 收到通知是否发出声音,默认为"true"
			"sound": "xx",		// 可选 通知声音，R.raw.[sound]. 
			"after_open": "xx",	// 必填 值为"go_app", "go_url", "go_activity", "go_custom"
		                           //	"go_app": 打开应用
		                           //	"go_url": 跳转到URL
		                           //	"go_activity": 打开特定的activity
		                           //	"go_custom": 用户自定义内容。
			"url": "xx",		// 可选 当"after_open"为"go_url"时，必填。  通知栏点击后跳转的URL，要求以http或者https开头  
			"activity": "xx",	// 可选 当"after_open"为"go_activity"时，必填。  通知栏点击后打开的Activity
			"custom": "xx"		// 可选 display_type=message, 或者
			//	display_type=notification且"after_open"为"go_custom"时，
			//	该字段必填。用户自定义内容, 可以为字符串或者JSON格式。
		};
		pbj.extra = {
			note: obj.note,
			tp: obj.tp,
			to: obj.to,
			date: obj.date,
			ev: obj.ev
		};
	}
	post.payload = pbj;
	post.production_mode = "true";	// 可选 正式/测试模式
	post.description = "xx";				// 可选 发送消息描述，建议填写。
	//post.thirdparty_id=key.replace(Aconf.cache.push,'');				// 可选 开发者自定义消息标识ID
	request.post({url:Aconf.apiurl.msg_send,'content-type':'application/json',body:JSON.stringify(post)}, function (err, response, json) {
		try{
			json=JSON.parse(json);
		}catch(e){}
		Afn.log('push ok umeng', err, json);
		if (json) {
		}
		if (cb) {
			cb(err, json);
		}
	});
	return false;
};

//用户登录后推送离线消息
Afn.push_last = function (_id, cb) {
	if (!cb) {
		cb = Afn.log;
	}
	Acache.hgetall(Aconf.cache.push + _id, function (err, rs) {
		if (err || !rs) {
			return cb(err ? err : 'no push last');
		}
		_.each(rs, function (v, k) {
			Afn.push_cache(_id, k, function (err, ls) {
				Afn.log('push last', err, ls);
			}, 1);
		});
		cb('push last ok');
	});
};

/**
 * 从cache推送消息至客户端
 *
 * @param _id   AcacheID
 * @param mid   消息ID
 * @param cb    回调函数
 * @param last  是否离线
 */
Afn.push_cache = function (_id, mid, cb, last) {
	Acache.hget(Aconf.cache.push + _id, mid, function (err, obj) {
		if (err || !obj) {
			return cb(err ? err : [Aconf.cache.push+_id,mid,'is not exist'].join(' '));
		}
		if (!obj.to) {
			return cb('no to user');
		}
		if (!obj.ev) {
			return cb('no ev');
		}
		var sids = Aimu[_id];
		if(!Acan.isArr(sids)){
			sids=[];
		}
		sids.forEach(function(sid){
			var akey = Acan.objGet(Aimc, sid + '._Akey', '').toLowerCase();
			//PC过滤重复推送
			if (akey.indexOf('pc') !== -1 && Acan.objGet(obj, 'status.pc', 0) === '1') {
				return;
			}
			//PC过滤重复推送
			if (akey.indexOf('wap') !== -1 && Acan.objGet(obj, 'status.wap', 0) === '1') {
				return;
			}
			//pad过滤重复推送
			if (akey.indexOf('pad') !== -1 && Acan.objGet(obj, 'status.pad', 0) === '1') {
				return;
			}
			if (sid && Aio.sockets.connected[sid]) {//在线用户直接推送
				try {
					Aio.sockets.connected[sid].emit(obj.ev, obj, mid);
					Afn.logger.debug('push ok', sid,obj);
				} catch (e) {
					Afn.logger.error('stack', 'push err', e.stack);
				}
				cb(null, 'push ok socket.io');
				//没有在线推送给phone时要给phone发离线推送
				if (akey.indexOf('phone') === -1) {
					if (!last) {
						Afn.push_device(obj, cb);
					}
				}
			} else {
				//离线用户推送至APNs
				//如果是离线消息则不推送
				if (!last) {
					Afn.push_device(obj, cb);
				}
			}	
		})
		
	});
};

//推送
Afn.push = function (obj,req){
	var mid = Acan.time('ms') + Acan.random(10, 99);//消息ID
	// obj克隆,防止异步冲突
	var clone = Acan.clone(obj);

	if (!clone || !clone.to) {
		return false;
	}
	if (!clone.note) {
		clone.note = '';
	}
	if (!clone.tp) {
		clone.tp = 'text';
	}
	if (!clone.date) {
		clone.date = Amoment().format();
	}
	if (clone.ev === 'review') {
		if (clone.tp === 'like') {
			clone.alert = clone.user.nickname + ':赞了我';
		} else {
			clone.alert = clone.user.nickname + ':' + clone.note;
		}
	}
	clone.mid = mid;
	var call = function (cbj,kto,kfrom) {
		var _from=kfrom?kfrom:cbj.from;
		Acache.hset(Aconf.cache.push + kto, mid, cbj);
		Acache.hget(Aconf.cache.unRead + kto,_from, function (err, rs) {
			if(err || !Acan.isNum(rs)){
				rs=0;
			}
			rs++;
			Acache.hset(Aconf.cache.unRead + kto,_from,rs);
		});
		var url = Aconf.im.protocol+req.getDomain('im.') + '/push?_id=' + kto + '&mid=' + mid;
		request.get({url:url,json:true,pool: {maxSockets: Infinity}}, function (err, response, json) {
			Afn.log('api push',clone.ev,url, kto, mid, err, json);
		});
	};
	var callGroup=function(){
		if(clone.ev==='msg'){
			Adb.msg_list.push(clone);
			call(clone,clone.to);
			return;
		}else if(clone.ev==='gmsg'){
			Adb.msg_group.get(req,{_id:clone.to},{},function(err,obj){
				var gbj=Acan.objGet(obj,'0',{});
				if(!gbj.is_member){//非群成员无权发送消息
					return;
				}
				Adb.msg_list.push(clone);
				var members=gbj.members;
				members.forEach(function(v){
					if(v.notice!==1 || v._id==req.Auser_id){
						return;
					}
					call(clone,v._id,Acan.objGet(obj,'0._id'));
				})
			});
		}
	}
	if (!clone.alert) {
		if (clone.from) {
			Adb.member.findById(clone.from, 'nickname').read('n').exec(function (err, doc) {
				if (doc && doc.nickname) {
					clone.alert = doc.nickname + ':' + clone.note;
				}
				callGroup();
			});
		} else {
			callGroup();
		}
	} else {
		callGroup();
	}
	return mid;
};

//推送的用户对象格式
Afn.push_user = function (obj) {
	var user = {};
	var allow = ['nickname', '_id', 'avatar'];
	allow.forEach(function (v, k) {
		if (obj[v]) {
			user[v] = obj[v];
		}
		else {
			user[v] = '';
		}
	});
	if (obj.profile && obj.profile.avatar) {
		user.avatar = obj.profile.avatar;
	}
	return user;
};

//发送给主进程 
Afn.pm_send = function (obj) {
	try {
		process.send(obj);
	} catch (e) {
	}
};

// IOSocket推送
Afn.io_emit = function (sid, ev) {
	if (Aio.sockets.connected[sid]) {
		try {
			Aio.sockets.connected[sid].emit(ev, arguments[2], arguments[3]);
		} catch (e) {
			console.log(e, e.stack);
		}
		return true;
	} else {
		return false;
	}
};

//data路径转换
Afn.datatoUrl=function(url,tp) {
	var rs = '', ext = '';
	if (!url) {
		return rs;
	}
	var fileNm = url.substr(url.lastIndexOf("/") + 1);
	if (!tp) {
		tp = 'm';
	}
	rs = url;
	var urr=url.split('.');
	if(urr.length>1){
		ext=urr.pop();
	}
	if(ext=='') ext='jpg';
	var rule = [
		{
			key: 'data/img',
			l: '/l.' + ext,
			m: '/m.' + ext,
			s: '/s.' + ext,
			dir: '',
			dirname: '/',
			fn: function (str, tp) {
				//return path.dirname(str).replace(this.key,"http://"+Aconf.domain.data+"/img")+this[tp];
				return "http://" + Aconf.oss.host + "/" + path.dirname(str) + this[tp];
			}
		},
		{
			key: "data/",
			l: '/l.' + ext,
			m: '/m.' + ext,
			s: '/s.' + ext,
			o: '/' + fileNm,    // 对应其他数据类型
			dir: '',
			dirname: '/',
			fn: function (str, tp) {
				//return path.dirname(str).replace('data/',"http://"+Aconf.domain.data+"/")+this[tp];
				return "http://" + Aconf.oss.host + "/" + path.dirname(str) + this[tp];
			}
		},
		{
			key: "http://" + Aconf.oss.host,
			l: '/l.' + ext,
			m: '/m.' + ext,
			s: '/s.' + ext,
			dir: '',
			dirname: '/',
			fn: function (str, tp) {
				if (str.substr(str.length - 6, 1) === '/' && str.substr(str.length - 4, 1) === '.') {
					str = path.dirname(str);
				}
				return str + this[tp];
			}
		},
		{
			key: "http://s3-media", l: 'l', m: 'm', s: 's', fn: function (str, tp) {
			return str.replace(/\/([\w]+)\./, '/' + this[tp] + '.');
		}
		}
	];
	rule.forEach(function (v, k) {
		if (url.indexOf(v.key) === 0) {
			rs = v.fn(url, tp);
			return false;
		}
	});
	return rs;
};


/**
 * 缓存用户组信息
 * @param cb
 */
Afn.cache_group = function (cb,f) {
	var load=function(){
		if (Adb.group && Adb.group.find) {
			Adb.group.find().read('n').exec(function (err, docs) {
				if (docs) {
					docs=Afn.docs_api(null,docs);
					var rs={};
					docs.forEach(function (doc, k) {
						rs[doc._id] = doc;
						if (cb) {
							cb();
						}
						Acache.hset(Aconf.cache.group, doc._id, doc);
					});
					gset(rs);
					Afn.logger.debug('load group OK', Appname);
				}
			});
		}
	}
	var gset=function(rs){
		Agroup = rs;
		AgroupGuest=Acan.arrFind(rs,'code','guest');
	}
	if (!Acan.isFun(cb)) {//初始化加载用户组信息
		Acache.hgetall(Aconf.cache.group, function (err, rs) {
			Afn.log(err,rs)
			if (!err && rs){
				gset(rs);
			}
			else load();
		});
		return;
	}
	load();
	//用户组信息不存在时加载
};

//根据用户组code获取group_id
Afn.groupCodeId = function (code) {
	var id = '';
	_.each(Agroup, function (doc, id) {
		if (doc.code === code) {
			id = doc._id;
			return true;
		}
	});
	return id;
};
/*
用户组权限判断
@req/group 传入req或者是group完整对象
@allow String/Array 允许的用户组
return boolean
*/
Afn.groupAllow=function(req,allow){
	if(!Acan.isArr(allow)) allow=[allow];
	var code=req.code;
	if(req.Agroup){
		code=req.Agroup.code;
	}
	if(!Acan.isArr(code)) code=[code];
	return !Acan.isEmpty(Acan.intersection(allow,code));
}
/*
获取用户的用户组信息
@user  用户对象
return group;
*/
Afn.groupGet=function(user,Appname){
	var group={code:[]},dgroup={};
	var gid=user.group || user.code || [];
	//多个用户组的code数组化合并
	var groupCode=function (g,v) {
		if(Acan.isStr(g.code)) g.code=[g.code];
		if(!g.code || !Acan.isArr(g.code)) g.code=[];
		if(g.code.indexOf(v.code)===-1) g.code.push(v.code);
	}
	_.each(Agroup,function(v,k){
		//加载用户组
		if(gid.indexOf(k)!==-1 || gid.indexOf(v.code)!==-1){
			if(!group.allow) Acan.extend(group,v);
			groupCode(group,v);
			group.allow=Afn.group_set(group.allow,v.allow);
		}
		//登录的用户加载默认的用户组
		if(v.app && v.app.indexOf(Appname)!=-1){
			if(!(dgroup.code)) Acan.extend(dgroup,v);
			groupCode(dgroup,v);
			dgroup.allow=Afn.group_set(dgroup.allow,v.allow);
		}
	});
	if(!group.allow && Acan.isEmpty(group.code) && dgroup.allow) Acan.extend(group,dgroup);
	return group;
}
Afn.group_set=function(pbj,cbj){
	var obj={};
	if(Acan.isObj(cbj)) obj=Afn.group_setc(obj,cbj);
	if(Acan.isObj(pbj)) obj=Afn.group_setc(obj,pbj);
	return obj;
}
Afn.group_setc=function(obj,cbj){
	_.each(cbj,function(v,app){
		if(!obj[app]) obj[app]={};
		if(Acan.isObj(v))
		_.each(v,function(mv,mod){
			if(!obj[app][mod]) obj[app][mod]={};
			if(Acan.isObj(mv))
			_.each(mv,function(av,act){
				if(!obj[app][mod][act]) obj[app][mod][act]=[];
				if(Acan.isArr(av))
					av.forEach(function(actv,i){
						if(obj[app][mod][act].indexOf(actv)==-1) obj[app][mod][act].push(actv);
					});
			});
		});
	});
	return obj;
}
Afn.html_note=function(str){
	return str.replace(/\n/g,'<br>').replace(/ /g,'&nbsp');
};

Afn.biz_cg_obj={};
Afn.biz_cg=function(tp) {
	var lang;
	var rs = {};
	var str = '';
	var langpath = Agl.root + 'lib/Yelp_cg/cn/category.json';
	if (fs.existsSync(langpath)) {
		str = fs.readFileSync(langpath);
	}
	try {
		lang = JSON.parse(str);
	} catch (e) {
		Afn.log('stack', e.stack);
	}
	Afn.biz_cg_obj = {};
	if (tp === 's') {
		rs = Afn.biz_cg_cs(lang);
	} else {
		Afn.biz_cg_c(lang);
		rs.cn = Afn.biz_cg_obj;
	}
	return rs;
};

Afn.biz_cg_c = function (arr) {
	if (arr.length > 0) {
		arr.forEach(function (v, k) {
			if (v.alias) {
				Afn.biz_cg_obj[v.alias] = v.title;
			}
			if (v.category.length > 0) {
				Afn.biz_cg_c(v.category);
			}
		});
	}
};

Afn.biz_cg_cs = function (arr, tp) {
	var obj = {};
	if (arr.length > 0) {
		arr.forEach(function (v, k) {
			if (v.alias) {
				obj[v.alias] = 1;
			}
			if (v.category.length > 0) {
				obj[v.alias] = Afn.biz_cg_cs(v.category, 1);
			}
		});
	}
	return obj;
};

Afn.biz_cg_fy = function (arr, to) {
	if (!to) {
		to = 'cn';
	}
	var biz_cg=Afn.biz_cg();
	var lang = biz_cg[to];
	if (Acan.isArr(arr) && arr.length > 0) {
		arr.forEach(function (v, k) {
			if (lang[v]) {
				arr[k] = lang[v];
			} else {
				Afn.log('no cg lang', v);
			}
		});
	}
	return arr;
};

//获取随机id
Afn.getDbid = function (db, bit, cb, i) {
	var id, min, max;
	if (!bit) {
		bit = 6;
	}
	min = Math.pow(10, bit - 1);
	max = Math.pow(10, bit) - 1;
	while (1) {/*}*/
		id = _.random(min, max);
		if (!/([\d])\1{3}/.test(id) && !/(8|6)\1{2}/.test(id)) {
			break;
		}//防止4连号，防止6、8的三连号
	}
	if (!i) {
		i = 0;
	}
	if (!db) {
		return id;
	}
	db.findOne({id: id}).read('n').exec(function (err, rs) {
		if (err) {
			return cb(err, 'getid error');
		}
		if (rs) {
			i++;
			if (i > 5) {
				return cb(1, 'getid error');
			}
			Afn.getDbid(db, bit, cb, i);
		} else {
			cb(err, id);
		}
	});
};


Afn.fy = function (q, from, to, cb) {
	var obj = Aconf.apiurl.fyFn(q, from, to, 'post');
	if (!cb) {
		cb = {};
	}
	var rs = {src: '', dst: ''};
	request.post({url:obj.url,form:obj.data}, function (err, response, data) {
		var json = {};
		try {
			json = JSON.parse(data);
		} catch (e) {
		}
		if (json && json.trans_result) {
			var num = json.trans_result.length - 1, ext = "\n";
			json.trans_result.forEach(function (v, k) {
				if (num === k) {
					ext = '';
				}
				rs.src += v.src + ext;
				rs.dst += v.dst + ext;
			});
			rs['auto'] = json.from;
			rs[json.from] = rs.src;
			rs[json.to] = rs.dst;
			cb(err, rs);
		} else {
			return cb(err ? err : json);
		}
	});
};
//根据地址获取geo信息 返回 [lat,lng]
Afn.address_geo = function (addr, cb) {
	request.get({url:Aconf.apiurl.geocodeAddressFn(addr),json:true,pool: {maxSockets: Infinity}}, function (err, response, json) {
		if (json.results && json.results.length > 0) {
			try {
				var geo = json.results[0].geometry.location;
				return cb([geo.lat, geo.lng]);
			} catch (e) {
				Afn.log('stack', e.stack);
				return cb(null);
			}
		}
	});
};
Afn.get_con=function(get,crr){
	var con={};
	if(Acan.isObj(get))
	for(var i in get){
		if(Acan.inArr(i,crr) && get[i].length>0) {
			con[i] = get[i];
		}
	}
	return con;
};

//文件上传路径保存到服务器中
Afn.upfile = function(fobj,spath,meta){
	var ext='';
	if(Acan.isObj(fobj)){
		if(fobj.originalname) ext=path.extname(fobj.originalname).toLowerCase();
		if(fobj.name) ext=path.extname(fobj.name).toLowerCase();
	}else if(Acan.isBase64(fobj)){
		//base64的文件上传要从内容中判断文件的类型
		if(Acan.isStr(meta)){
			try{meta=JSON.parse(meta);}catch(e){}
			if(Acan.isObj(meta) && meta.name){
				ext=path.extname(meta.name).toLowerCase()
			}
		}
		var bext='';
		try{
			bext = '.'+fobj.substring(5,fobj.indexOf(';')).split('/').pop();
		}catch(e){}
		if(bext=='.jpeg') bext='.jpg';
		if(ext!=bext){
			ext=bext;
		}
	}
	//  TODO 所有文件上传后表示为l.???  meiyb
	var savepath = spath+moment().format("/YYYY/MMDD/HHmmssSSS")+_.random(0,9)+'/l'+ext;
	Acan.mkdirs(path.dirname(savepath));
	if(fobj.path){
		fs.renameSync(fobj.path,Agl.root+savepath);
	}else if(Acan.isBase64(fobj)){
		fs.writeFileSync(Agl.root+savepath,fobj.substr(fobj.indexOf(';')+8),{encoding:'base64'});
	}
	if(['.jpg','.png','.gif'].indexOf(ext)!==-1){
		//保留原图
		readable = fs.createReadStream(savepath);
		// 创建写入流
		writable = fs.createWriteStream(savepath.replace('/l'+ext,'/o'+ext));
		readable.pipe(writable);
	}
	return savepath;
};
Afn.rmdir=function(dirpath,cb){
	var rmdir=require('rmdir');
	if(!fs.existsSync(dirpath)){
		if(cb) {
			cb('no dir or file');
		}
		return;
	}
	if(fs.lstatSync(dirpath).isFile()){
		dirpath=path.dirname(dirpath);
	}
	if(fs.lstatSync(dirpath).isDirectory()) {
		rmdir(dirpath, function (err, dir, files) {
			if (cb) {
				cb(err, dir, files);
			}
		});
	}
};

Afn.data=function(){

};
/**
 * OSS数据同步方法
 *
 * @param dataPath
 * @param cb
 */
Afn.data.oss = function (dataPath, cb) {
	Afn.img.oss(dataPath, cb);
};

Afn.img=function(){
	
};
//同步图片到oss
Afn.img.oss=function(imgpath,cb){
	if(fs.existsSync(imgpath) && fs.lstatSync(imgpath).isDirectory()){
		var child=fs.readdirSync(imgpath);
		if(child.length<=0){
			if(cb) {
				cb('oss no files');
			}
			return false;
		}
		var ccbs=Acan.ccb(child.length,function(){
			if(cb) {
				cb('oss ok');
			}
		});
		child.forEach(function(val,i){
			var npath=imgpath+'/'+val;
			Aoss.putObject({bucket:Aconf.oss.bucket,object:npath,srcFile:Agl.root+npath},function(err){
				if(err) {
					Afn.log('oss err', err);
				}
				ccbs.cb();
			});
		});
	}else{
		if(cb) {
			cb('oss path err');
		}
	}
};

Afn.img.oss_del = function (imgpath, cb) {
	if (!fs.existsSync(imgpath)) {
		if (imgpath.indexOf('.') !== -1) {
			imgpath = path.dirname(imgpath);
		}
	} else {
		if (fs.lstatSync(imgpath).isFile()) {
			imgpath = path.dirname(imgpath);
		}
	}
	Aoss.listObject({bucket: Aconf.oss.bucket, prefix: imgpath}, function (err, rs) {
		if (!err && rs.ListBucketResult.Contents) {
			try {
				rs.ListBucketResult.Contents.forEach(function (v, k) {
					Aoss.deleteObject({bucket: Aconf.oss.bucket, object: v.Key[0]}, function (err, res) {
						if (cb) {
							cb('oss_del', err);
						}
					});
				});
			} catch (e) {
				Afn.log('stack', e.stack);
			}
		}
	});
};

//图片优化
Afn.img.resize=function(fname,spath,w,h,q,cb,crop){
	var im=require('imagemagick');
	var resize='',arg=['-auto-orient','-colorspace','sRGB','-interlace','line','-strip'];

	im.identify(fname,function(err,rs){
		if(err){
			Afn.log(err);
			return ;
		}
		var min;
		if(crop){
			if(rs.width>=rs.height){
				min=rs.height;
				arg.push('-crop',min+'x'+min+'+'+(rs.width-rs.height)/2+'+0');
			}else{
				min=rs.width;
				arg.push('-crop',min+'x'+min+'+0+'+(rs.height-rs.width)/2);
			}
		}
		if(w && h) {
			resize = w + 'x' + h;
		}
		if(w && h) {
			resize = w + 'x' + h;
		}
		if(resize!==''){
			arg.push('-resize');
			arg.push(resize);
		}
		if(!q) {
			q = 85;
		}
		if(spath.substr('-4')==='.png'){
			arg.push('-depth','8');
			arg.push('-compress','Zip');
			arg.push('-quality',100);
			//arg.push('-define','png:format=png8','png:compression-level=9');
		}else{
			arg.push('-depth','16');
			arg.push('-quality',q);
			arg.push('-compress','JPEG');
		}
		if(!fname || !spath){return false;}
		else{arg.unshift(fname);arg.push(spath);}
		if(!cb) {
			cb = Afn.log;
		}
		im.convert(arg,cb);
	});
};

//默认优化
Afn.img.opt = function (fname, cb,tp) {
	if(!tp) tp='general';
	var ext = 'jpg', spath = fname.toLowerCase();
	var dirname = path.dirname(spath);
	if(spath.indexOf('.')!==-1){
		ext=path.extname(spath).toLowerCase();//获取文件的扩展名
	}
	var ccb = Acan.ccb(3, function () {
		Afn.img.oss(dirname, function (err) {
			if (Acan.isFun(cb)) {
				cb(err, spath);
			}
		});
	});
	var crop=0;
	if(tp=='avatar'){
		crop=1;
	}
	Afn.img.resize(Agl.root + spath, Agl.root + dirname + '/s' + ext, Aconf.image[tp].width_s, Aconf.image[tp].height_s, 85, function (err) {
		ccb.cb();
	},crop);
	Afn.img.resize(Agl.root + spath, Agl.root + dirname + '/m' + ext, Aconf.image[tp].width_m, Aconf.image[tp].height_m, 85, function (err) {
		ccb.cb();
	},crop);
	Afn.img.resize(Agl.root + spath, Agl.root + dirname + '/l' + ext, Aconf.image[tp].width, Aconf.image[tp].height, 85, function (err) {
		ccb.cb();
	},crop);
	return Agl.root + dirname;
};

//图片删除
Afn.img.del = function (fname) {
	if (!fname) {
		return false;
	}
	if (fname.length < 3) {
		return false;
	}
	//过滤非法路径
	if (fname.indexOf('..') !== -1) {
		return false;
	}
	// 如果路径包含//替换成/
	var frr = fname.replace(/\/\//g,'/').split('/');
	if (frr.length > 3 && frr[0] === 'data' && frr[1].length > 1) {
		Afn.img.oss_del(fname);
		Afn.rmdir(Agl.root + fname);
	}
};
Afn.logger = require("tracer").colorConsole({
	format: [
		"[{{timestamp}}] [{{title}}] {{message}} (at \n{{path}}", //default format
		{
			error: "{{timestamp}} [{{title}}] {{message}} (in {{file}}:{{line}})\nCall Stack:\n{{stack}}" // error format
		}
	],
	dateformat: "HH:MM:ss.L",
	preprocess: function (data) {
		var line = ['err', 'log', 'stack'];
		var type = '', str = Acan.time('H:i:s') + '|';// + data.path.replace(/\\/g, '/').replace(Agl.root, '') + ':' + data.line + '|';
		var p='';
		data.stack.replace(/    at /g,'').replace(/\\/g,'/').split('\n').forEach(function(v,k){
			if(v.indexOf(Agl.root)!=-1){
				p+="\t"+v+"\n"
			}
		});
		str+=p;
		data.path=p;
		if (Acan.isStr(data.args[0])) {
			type = data.args[0];
		}
		for (var i = 0; i < data.args.length; i++) {
			str += JSON.stringify(data.args[i]) + ',';
		}
		str += "\n";
		var logpath = Agl.root + 'data/log/' + Acan.time('Y/md') + '.log';
		if (line.indexOf(type) !== -1) {
			logpath = logpath.replace('.log', type + '.log');
		}
		Acan.mkdirs(path.dirname(logpath));
		fs.appendFileSync(logpath, str);
		data.title = data.title.toUpperCase();
		if(Agl.logio){
			process.send({mod:'log',log:str});
		}
	}
});

Afn.log=Afn.logger.warn;
//logger 重定义 非debug模式不打印
Afn.logInfo=Afn.logger.info;
Afn.logger.info=function(){
	if(!Agl.isDebug){
		return;
	}else{
		Afn.logInfo.apply(Afn.logInfo,arguments);
	}
}
Afn.logDebug=Afn.logger.debug;
Afn.logger.debug=function(){
	if(!Agl.isDebug){
		return;
	}else{
		Afn.logDebug.apply(Afn.logDebug,arguments);
	}
}
Afn.logC=console.log;
console.log=function(){
	arguments[arguments.length]='console.log';
	Afn.logC.apply(Afn.log,arguments);
}

//日志 
Afn.log2 = function () {
	var line = ['err', 'log', 'stack'];
	var type = '';
	if (Acan.isStr(arguments[0])) {
		type = arguments[0];
	}
	if (Apphost === 'debug') {
		Afn.logger.debug.call(this, arguments);
	} else {
		if (appmode !== 'line') {
			if (type === 'stack') {
				console.trace.apply(Appname, arguments);
			} else {
				console.trace.apply(Appname, arguments);
			}
		}
	}
	var str = '';
	for (var i = 0; i < arguments.length; i++) {
		str += Acan.time('H:i:s') + ":" + JSON.stringify(arguments[i]) + '\n';
	}
	var logpath = Agl.root + 'data/log/' + Acan.time('Y/md') + '.log';
	if (line.indexOf(type) !== -1) {
		logpath = logpath.replace('.log', type + '.log');
	}
	Acan.mkdirs(path.dirname(logpath));
	fs.appendFileSync(logpath, str);
};
//数据处理 docs to api
Afn.docs_api = function (req, docs,cb) {
	var arr = [], args = [], ai = 0;
	for (var i in arguments) {
		if (i > 1) {
			args.push(arguments[i]);
			ai++;
		}
	}
	if(Acan.isFun(args[args.length-1])){
		var ccb=Acan.ccb(1,function(){
			args[args.length-1](arr);
		});
	}
	if (_.isArray(docs)) {
		docs.forEach(function (v, k) {
			if (v.doc_api) {
				if(ccb){
					ccb.at();
					v.doc_api(req, args[0], function(obj){
						if(obj) arr.push(obj);
						ccb.cb();
					});
				}else{
					arr.push(v.doc_api(req, args[0], args[1]));
				}
			} else if (v.toObject) {
				arr.push(v.toObject());
			} else {
				arr.push(v);
			}
		});
	}
	if(ccb) ccb.cb();
	return arr;
};

//得到大众点评的签名
//除appkey与secret外，其他算法请勿私自修改
Afn.getSign = function (param) {
	// 定义申请获得的appKey和appSecret
	var appkey = Aconf.openapi.dianping.key;
	var secret = Aconf.openapi.dianping.secret;
	// 创建参数表
	/*var param = {};
	 param["city"]="上海";
	 param["latitude"]="31.21524";
	 param["longitude"]="121.420033";
	 param["category"]="美食";
	 param["region"]="长宁区";
	 param["limit"]="20";
	 param["radius"]="2000";
	 param["offset_type"]="2";
	 param["has_coupon"]="1";
	 param["has_deal"]="1";
	 param["keyword"]="泰国菜";
	 param["sort"]="7";*/
	// 对参数名进行字典排序
	var array = [];
	for (var key in param) {
		if (param.hasOwnProperty(key)) {
			array.push(key);
		}
	}
	array.sort();
	// 拼接有序的参数名-值串
	var paramArray = [];
	paramArray.push(appkey);
	for (var index in array) {
		var key = array[index];
		paramArray.push(key + param[key]);
	}
	paramArray.push(secret);
	// 字符串连接示例
	// XXXXXXXXcategory美食city上海formatjsonhas_coupon1has_deal1keyword泰国菜latitude31.21524limit20longitude121.420033offset_type0radius2000region长宁区sort7XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	// SHA-1编码，并转换成大写，即可获得签名
	var shaSource = paramArray.join("");
	var sign = new String(Acan.SHA1(shaSource)).toUpperCase();
	//签名示例 7D78381BC58E1DB1DBA4BD965916FE6B4D5DC892
	return sign;
};
//判断数据类型
Afn.type = function (obj) {
	var class2type = {}, typeall = "Boolean Number String Function Array Date RegExp Object Error".split(" ");
	for (var i = 0; i < typeall.length; i++) {
		class2type["[object " + typeall[i] + "]"] = typeall[i];
	}
	if (obj == null) {
		return String(obj);
	}
	return typeof obj === 'object' ? class2type[Object.prototype.toString.call(obj)].toLowerCase() : typeof obj;
};


/**
 * 后台用 过滤数据
 */
Afn.SearchDate=function(model,con,_date){
	if(!_date || !Adb[model]){
		return con;
	}
	if(Acan.isObjectId(con._id)){
		return con;
	}
	if(!(_date && _date.start && _date.end)){
		return con;
	}
	var mongoose = require('mongoose');
	var start=Acan.time("Y-m-d 00:00:00",_date.start);//设置开始日期
	var end=Acan.time("Y-m-d 23:59:59",_date.end);//设置开始日期
	if(_date.start.indexOf(' ')!==-1){
		start=Acan.time("Y-m-d H:i:00",_date.start);
		end=Acan.time("Y-m-d H:i:59",_date.end);
	}
	if(_date.start.indexOf('T')!==-1){//8小时差
		start=Acan.time("Y-m-d H:i:00",Acan.time('s',_date.start)-8*3600);
		end=Acan.time("Y-m-d H:i:59",Acan.time('s',_date.end)-8*3600);
	}
	//console.log(Acan.time('Y-m-d H:i:s',Acan.time('s',start)));
	//console.log(Acan.time('Y-m-d H:i:s',Acan.time('s',end)));
	var dstart=Acan.time('s',start).toString(16)+'0000000000000000';
	var dend=Acan.time('s',end).toString(16)+'0000000000000000';
	if(con._id){
		con._id=Acan.extend(con._id,{$gte:new mongoose.Types.ObjectId(dstart),$lte:new mongoose.Types.ObjectId(dend)});
	}else{
		con._id={$gte:new mongoose.Types.ObjectId(dstart),$lte:new mongoose.Types.ObjectId(dend)};
	}
}
/**
 * DataTable用 搜索功能
 */
Afn.Search=function(model,con,_search){
	if(!_search || !Adb[model]){
		return con;
	}
	var operator;
	for(var i in _search){
		var v=_search[i];
		if(i.indexOf('.')!==-1){
			var irr=i.split('.');
			operator=irr[1];
			i=irr[0];
		}
		var model_path=Adb[model].schema.path(i);
		if(!model_path) continue;
		switch(model_path.instance){
			case 'String':
				if(Acan.isArr(v)){
					con[i]={$in:v}
				}else{
					con[i]=new RegExp(v);
				}
			break;
			case 'Array':
				if(Acan.isArr(v)){
					con[i]={$in:v}
				}else{
					con[i]={$in:[v]};
				}
			break;
			case 'ObjectID':
			case 'Number':
				con[i]=v;
			break;
		}
		if(operator && Acan.isInts(v)){
			if(!Acan.isObj(con[i])){
				con[i]={};
			}
			con[i]['$'+operator]=Acan.int(v);
		}
	};
	console.log(con)
	return con;
}
/**
 * DataTable用数据
 * @memberOf Afn
 * @param req
 * @param res
 * @param model {String}模型名
 * @param regSearchNm {String}正则查询字段名
 * @param next
 * @param con
 * @param opt
 * @param cb
 * @param ifDocCb
 */
Afn.getListData = function (req, res, model, regSearchNm, next, con, opt, cb, ifDocCb,toObj) {
	var populate,select=null;
	if(arguments.length=='4' && Acan.isObj(arguments[3])){
		next=arguments[2];
		var _bj=arguments[3];
		regSearchNm=_bj.regSearchNm;
		model=_bj.model;
		con=_bj.con;
		opt=_bj.opt;
		cb=_bj.cb;
		populate=_bj.populate?_bj.populate:[];
		ifDocCb=_bj.ifDocCb;
	}
	if(toObj!=false) toObj=true;
	var rs = {pre: 1, next: 2, page: 1, num: 0, total: 0, data: []};
	var get = req.query;
	if (!con) {
		con = {};
	}
	if (!_.isObject(opt)) {
		opt = {skip: 0, limit: 10};
	} else if ((!opt.skip && !opt.limit)) {
		opt.skip = 0;
		opt.limit = 10;
	}
	if (!opt.sort) {
		opt.sort = {_id: -1};
	}
	if (get.type === 'datatable' || get.datatable === '1') {
		if (get.search && get.search.value) {
			//支持多属性正则搜索
			var sreg = new RegExp(get.search.value.replace(/\./g,'\\.'));
			if(Acan.isArr(regSearchNm) && regSearchNm.length>1){
				con['$or']=[];
				regSearchNm.forEach(function(v){
					var _obj={};
					_obj[v]=sreg;
					con['$or'].push(_obj);
				});
			}else{
				if(Acan.isArr(regSearchNm)){
					con[regSearchNm[0]]=sreg
				}else{
					con[regSearchNm]=sreg;
				}
			}
		}
		if (get.columns) {
			get.columns.forEach(function (v) {
				if (v.search.value) {
					con[v.data] = {$in: v.search.value.split(',')};
				}
			});
		}
		opt.limit = parseInt(get.length);
		opt.skip = parseInt(get.start);
	}
	Afn.Search(model,con,get._search);
	Afn.SearchDate(model,con,get._date);
	if (get.count) {
		opt.limit = parseInt(get.count);
	}
	//计算页码
	if (get.page) {
		opt.skip = (parseInt(get.page) - 1) * opt.limit;
	}else{
		get.page=1;
	}
	//计算开始位置
	rs.page = parseInt(get.page);
	rs.pre = get.page - 1;
	if (rs.pre < 1) {
		rs.pre = 1;
	}
	rs.next = Acan.int(get.page) + 1;
	var call = function () {
		if (cb) {
			cb(rs);
		} else {
			res.api_rs(rs);
		}
	};
	Adb[model].count(con).read('n').exec(function (err, count) {
		if (err) {
			return res.api_err(err);
		}
		rs.total = count;
		if(rs.next>Math.floor(count/opt.limit)+1) rs.next=rs.page;
		if (get.type === 'datatable') {
			rs.recordsFiltered = count;
			rs.recordsTotal = count;
		}
		if (count<1) {
			return call();
		}
		// populate追加
		if(!Acan.isEmpty(populate) && Acan.isObj(populate)){
			populate=[populate];
		}else if(!Acan.isArr(populate)){
			populate=[];
		}
		if(Acan.isObj(opt.pop) && opt.pop.path){
			opt.pop=[opt.pop];
		}
		if(Acan.isArr(opt.pop)){
			opt.pop.forEach(function(v,k){
				populate.push(v);
			});
		}
		if(opt.select){
			if(Acan.isArr(opt.select)){
				select=opt.select.join(' ');
			}else if(Acan.isStr(opt.select)){
				select=opt.select;
			}
			delete opt.select;
		}
		var find = Adb[model].find(con, select, opt);
		if(!Acan.isEmpty(populate)){
			find = find.populate(populate);
		}
		find.read('n').exec(function (err, data) {
			if (err || !data) {
				return call();
			}
			rs.num = data.length;
			//不需要doc_api 直接返回doc时
			if(toObj===false){
				rs.data = data;//这里返回的是doc 
				call();
				return;
			}
			// doc_api需要回调时
			if (!ifDocCb) {
				rs.data = Afn.docs_api(req,data);
				call();
				return;
			}
			var ret = [];
			if (data.length<1) {
				return call();
			}
			data.forEach(function (v, i) {
				v.doc_api(req, function (err, result) {
					if (err) {
						return res.api_err(err);
					}
					ret.push(result);
					if (i === (data.length - 1)) {
						rs.data = ret;
						call();
					}
				});
			});
		});
	});
};

/**
 * Javascript设置要保留的小数位数，四舍五入返回
 *
 * @param number        元数字
 * @param scale         小数位精度
 * @returns {number}
 */
Afn.round = function (number, scale) {
	return Math.round(number * Math.pow(10, scale)) / Math.pow(10, scale);
};

/**
 * 物理删除通用方法
 *
 * @param req
 * @param res
 * @param model 模块名
 * @returns {*} 处理结果
 */
Afn.del = function (req, res, model) {
	var id = req.query._id;
	if (!id) {
		return res.api_err({'param': model, 'message': 'no _id'});
	}
	Adb[model].remove({_id: req.query._id}, function (err, rs) {
		if (err) {
			return res.api_err(err);
		}
		return res.api_rs(rs);
	});
};

/**
 * 逻辑删除通用方法
 *
 * @param req
 * @param res
 * @param model 模块名
 * @returns {*} 处理结果
 */
Afn.logicDelete = function (req, res, model,del) {
	var id = req.query._id,tp;
	if (!id) {
		return res.api_err({'param': model, 'message': 'no _id'});
	}
	//不传del 默认为删除
	if(!Acan.isDefined(del)) del=1;
	if(del===0){
		tp='restore';
	}else{
		tp='remove';
	}
	// del: 1 逻辑删除
	Adb[model].findById(id,'del',function (err, doc) {
		var _old=JSON.parse(JSON.stringify(doc));
		doc.set('del',del);
		Adb.oplog.add(req,model,doc,'remove',[_old,JSON.parse(JSON.stringify(doc))],function(err,logDoc){
			doc.save(function (err, rs) {
				if (err || !rs) {
					return res.api_err(err ? err : 'no doc');
				}
				res.api_rs(doc);
			});
		},function(err){
			return res.api_err(err);
		});	
	});
};
/**
 * 逻辑删除恢复通用方法
 *
 * @param req
 * @param res
 * @param model 模块名
 * @returns {*} 处理结果
 */
Afn.restoreData = function (req, res, model) {
	return Afn.logicDelete(req,res,model,0);
};

/**
 * 上传图片共通方法
 * 上传图片到OSS指定目录,同步返回服务器路径
 *
 * @param req
 * @param cb
 * @param full  传入的情况下返回全路径
 */
Afn.up_pic = function (req, cb, full) {
	var post = req.body;
	var fileMeta = post.filemeta;
	var fileData = post.filedata;

	var serverPath;
	// 网页Base64上传
	if (fileMeta && fileData) {
		serverPath = Afn.upfile(fileData, Aconf.path.image, JSON.parse(fileMeta));
		// APP端直接2进制文件上传
	} else if (req.files && req.files.file) {
		serverPath = Afn.upfile(req.files.file, Aconf.path.image);
	}
	Afn.img.opt(serverPath, function (err, path) {
		Afn.log(err, path);
		if (full) {
			serverPath = Afn.datatoUrl(serverPath);
		}
		if(Acan.isFun(cb)) cb(null,{url: serverPath});
	});

	var pic = {};
	pic.uid = req.Auser_id;
	pic.url = serverPath;
	pic.date = new Date();
	Adb.tmp_pic.add(pic);
};

//根据latlng查地址
Afn.geoCodes = function (obj, cb) {
	var request = require('request'),rs={};
	if (obj.latlng && obj.latlng.length > 0) {
		url = Aconf.apiurl.geocodeFn(obj.latlng, obj.lang || '');
	} else if (obj.address && obj.address.length > 0) {
		url = Aconf.apiurl.geocodeAddressFn(obj.address, obj.lang || '');
	} else {
		return cb('no latlng/address');
	}
	request.get({url: url, json: true,pool: {maxSockets: Infinity}}, function (err, r, json) {
		if (err) {
			return cb(err);
		}
		var rs=Acan.objGet(json,'results.0')
		if (rs) {
			var grs = rs;
			rs.addr = [];
			rs.address = grs.formatted_address;
			grs.address_components.forEach(function (v, k) {
				rs.addr.push(v.long_name);
				if (Acan.inArr('administrative_area_level_1',v.types)) {
					rs.province = v.long_name;
				}else if (Acan.inArr('locality',v.types)) {
					rs.city = v.long_name;
				}else if (Acan.inArr('sublocality_level_1',v.types)) {
					rs.district = v.long_name;
				}else if (Acan.inArr('country',v.types)) {
					rs.country = v.long_name;
					rs.cc = v.short_name;
				}else if (Acan.inArr('route',v.types)) {
					rs.route = v.short_name;
				}else if (Acan.inArr('street_number',v.types)) {
					rs.street_number = v.short_name;
				}
			});
			var geo = grs.geometry.location;
			rs.lat = geo.lat;
			rs.lng = geo.lng;
			rs.geo = [geo.lat, geo.lng];
		}
		return cb(err,rs);
	});
}
/*
	将超过1000的数字转换成1K的形式
*/
Afn.thousandize = function(str){
	var num = Acan.int(str);
	if(isNaN(num)) {
		num = '';
	} else if(num >= 1000) {
		num = Math.floor(num/1000) + '.' +  Math.floor((num%1000)/100) + 'K';
	}
	return num;
}
/*
1、根据ip判断国家，根据国家决定默认的货币单位
2、根据语言判断
*/
Afn.getCurrency = function(req){
	var cr='';
	var allow={US:'USD',AU:'AUD',NZ:'NZD',CN:'CNY'};
	var area={US:'美国',AU:'澳大利亚',NZ:'新西兰'};
	//美国   澳大利亚  新西兰   中国就精确到城市了。
	var ip=req.Aip;
	var cy=ip_country(ip);
		var chkLang=function(){
			var cc=Acan.objGet(req.headers['accept-language'].match(/-(\w+)/g),'0','');
			cc=cc.replace('-','').toUpperCase();
			if(allow[cc]){
				cr=allow[cc];
			}else{
				cr='USD';
			}
			return cr;
		}
		var counry=Acan.objGet(cy,'Counry');
		if(!counry){
			return chkLang();
		}
		_.each(area,function(v,k){
			if(v==counry){
				cr=allow[k];
			}
		})
		if(cr){
			return cr;
		}else{
			return chkLang();
		}
}
function ip_country(ip){
	var qqwry=require('lib-qqwry').info();
	var rs={};
	if(Acan.isEmpty(ip)){
		return;
	}
	rs=qqwry.searchIP(ip);
	return rs;
}
Afn.check_price=function(fromCode,toCode,price,callback){
	var rsPrice=price;
	Acache.hget('currency_USD', fromCode, function (ferr, frs) {
		if (ferr) {
			Afn.log('member_wallet->check_price->fromcode error');
			return callback('fromcode error');
		}
		if(frs>0) rsPrice=price/frs;
		Acache.hget('currency_USD', toCode, function (terr, trs) {
			if (terr) {
				Afn.log('member_wallet->check_price->toCode error');
				return callback('toCode error',rsPrice);
			}
			if(trs>0) rsPrice=rsPrice*trs;
			return callback(null,rsPrice); 
		});
		return false;
	});
}
Afn.dwz_create=function(url,callback){
	//@短网址生成
	var request = require('request');
	if(!url){
		return callback('url error');
	}
	request.get({url:Aconf.apiurl.dwz_create+"&url_long="+url,pool: {maxSockets: Infinity}}, function (err, response, json) {
		if(err){
			return callback(err);
		}
		if(err || !json){
			return callback(err?err:'no json request');
		}
		var jsonObj = JSON.parse(json);
		return callback(null,jsonObj.urls[0].url_short);
	});
}
Afn._query=function(tinyurl,callback){
	//@短网址还原
	var request = require('request');
	if(!tinyurl){
		return callback('tinyurl error');
	}
	request.post({url:Aconf.apiurl.dwz_query,form:{tinyurl:tinyurl}}, function (err, response, json) {
		if(!json){
			return callback('request error');
		}
		var jsonObj = JSON.parse(json);
		if(jsonObj.status && jsonObj.status!=0){
			return callback(jsonObj.err_msg);
		}
		return callback(null,jsonObj.longurl);
	});
}
module.exports = Afn;
